package com.ckerchina.admin.ckadmin.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ckerchina.admin.ckadmin.consts.JPushAuth;

import cn.jpush.api.JPushClient;
import cn.jpush.api.common.resp.APIConnectionException;
import cn.jpush.api.common.resp.APIRequestException;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Options.Builder;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.audience.AudienceTarget;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;

/**
 * Code 描述 详细解释 实际提示信息 HTTP Status Code 1000 系统内部错误 服务器端内部逻辑错误，请稍后重试。 500 1001 只支持 HTTP Post 方法 不支持 Get 方法。 405 1002
 * 缺少了必须的参数 必须改正。 400 1003 参数值不合法 必须改正。 400 1004 验证失败 必须改正。详情请看：调用验证 401 1005 消息体太大 必须改正。 通知 “iOS”:{ } 内的总体长度不超过：220
 * 个字节（包括自定义参数和符号）。JPush 的 消息加通知 部分长度不超过 1K 字节。 400 1008 app_key参数非法 必须改正。 400 1011 没有满足条件的推送目标 请检查audience 400 1020 只支持
 * HTTPS 请求 必须改正。 404 1030 内部服务超时 稍后重试。 503
 */
public class JPushUtil {

	private static Logger logger = LoggerFactory.getLogger(JPushUtil.class);

	private static Integer DAY = 86400;

	private static Map<String, JPushClient> jpushClientMap = new HashMap<String, JPushClient>();

	static {
		for (JPushAuth auth : JPushAuth.values()) {
			String app = auth.getApp();
			JPushClient jpushClient = new JPushClient(auth.getMasterSecret(), auth.getAppKey(), 3);
			jpushClientMap.put(app, jpushClient);
		}
	}

	/**
	 * 全部用户推送消息
	 * 
	 * @param app
	 * @param content
	 * @param isProduction
	 * @param liveDays
	 * @return
	 */
	public static Long sendNotification2All(String app, String content, Boolean isProduction, Integer liveDays) {
		PushPayload payload = PushPayload.alertAll(content);
		if (isProduction != null) {
			payload.resetOptionsApnsProduction(isProduction);
		}
		if (liveDays != null && liveDays > 0) {
			payload.resetOptionsTimeToLive(DAY * liveDays);
		}
		PushResult pushResult = sendPush(app, payload);
		if (pushResult == null) {
			return null;
		}
		Long msgid = pushResult.msg_id;
		logger.info("sendNotification2All app:{} content:{}", app, content);
		return msgid;
	}

	/**
	 * 給指定用户推送消息
	 * 
	 * @param app
	 * @param title
	 * @param content
	 * @param registrationIdList
	 * @param extras
	 * @param options
	 * @return
	 */
	public static Long sendNotificationByRegistrationId(String app, String title, String content,
			List<String> registrationIdList, Map<String, String> extras, Options options) {
		if (registrationIdList == null || registrationIdList.isEmpty()) {
			return null;
		}
		logger.info("发送推送消息 app:{} title:{} content:{}", app, title, content);
		cn.jpush.api.push.model.notification.AndroidNotification.Builder androidBuilder = AndroidNotification
				.newBuilder();
		cn.jpush.api.push.model.notification.IosNotification.Builder iosBuilder = IosNotification.newBuilder();
		if (StringUtils.isNotEmpty(title)) {
			androidBuilder.setTitle(title);
		}
		if (extras != null && extras.size() > 0) {
			androidBuilder.addExtras(extras);
			iosBuilder.addExtras(extras);
		}
		AndroidNotification androidNotification = androidBuilder.build();
		IosNotification iosNotification = iosBuilder.setSound("happy").autoBadge().build();

		Notification notification = Notification.newBuilder().setAlert(content)
				.addPlatformNotification(androidNotification).addPlatformNotification(iosNotification).build();
		cn.jpush.api.push.model.PushPayload.Builder builder = PushPayload.newBuilder()
				.setPlatform(Platform.android_ios()).setAudience(Audience.newBuilder()
						.addAudienceTarget(AudienceTarget.registrationId(registrationIdList)).build())
				.setNotification(notification);
		if (options != null) {
			builder.setOptions(options);
		}
		PushPayload payload = builder.build();
		PushResult pushResult = sendPush(app, payload);
		if (pushResult == null) {
			return null;
		}
		Long msgid = pushResult.msg_id;
		logger.info("sendNotificationByRegistrationId app:{} title:{} content:{} registrationIdList:{} extras:{}", app,
				title, content, registrationIdList, extras);
		return msgid;
	}

	public static Long sendAll(String app, String msg) {
		PushPayload payload = PushPayload.alertAll(msg);
		PushResult pushResult = sendPush(app, payload);
		if (pushResult == null) {
			return null;
		}
		Long msgid = pushResult.msg_id;
		logger.info("sendAll app:{} msg:{} msgid:{}", app, msg, msgid);
		return msgid;
	}

	public static Options getOptions(Boolean isProduction, Integer liveDays) {
		Builder builder = Options.newBuilder();
		if (isProduction != null) {
			builder.setApnsProduction(isProduction);
		}
		if (liveDays != null) {
			builder.setTimeToLive(DAY * liveDays);
		}
		return builder.build();
	}

	private static PushResult sendPush(String app, PushPayload pushPayload) {
		JPushClient client = getJPushClient(app);
		if (client == null) {
			return null;
		}
		PushResult pushResult = null;
		try {
			pushResult = client.sendPush(pushPayload);
		} catch (APIConnectionException e) {
			logger.error("Connection error, should retry later", e);
		} catch (APIRequestException e) {
			logger.error("Should review the error, and fix the request", e);
			logger.info("HTTP Status: " + e.getStatus());
			logger.info("Error Code: " + e.getErrorCode());
			logger.info("Error Message: " + e.getErrorMessage());
		}
		return pushResult;
	}

	private static JPushClient getJPushClient(String app) {
		return jpushClientMap.get(app);
	}

}
